#!/usr/bin/slua

package.path  = "./?.lua;/etc/init/?.lua" .. ";".. package.path

l5=require("l5")
color=require("ansicolors")
config=require("config")

local function cwrite(str,clr)
  if os.getenv("init_color") == "1" or l5.getppid() == 1 then
    str=color("%{"..clr.."}"..str)
  end
  io.write(str)
end

function get_content(filename)
	local t=nil
	local f = io.open(filename, "r")
	if f ~= nil then
		t = f:read('*all')
		f:close()
	end
	return t
end

local function kernel_config(task)
	local t=nil
	local cfg=""
	local value=""
	local poz=-1
	local cmdline=get_content("/proc/cmdline")
	while cmdline:find(task) do
		_,poz=cmdline:find(task)
		if cmdline:sub(poz+1,poz+1) == "." then
			if not t then t={} end
			cmdline=cmdline:sub(poz+2,cmdline:len())
			poz=cmdline:find("=")
			cfg=cmdline:sub(1,poz-1)
			if cmdline:find(" ") then
				value=cmdline:sub(poz+1,cmdline:find(" ")-1)
			else
				value=cmdline:sub(poz+1,cmdline:len())
			end
			t[cfg]=value
		else
			cmdline=cmdline:sub(poz+1,cmdline:len())
		end
	end
	
	return t
end

function shell(command)
	local handle=io.popen(command)
	local result=handle:read('*all')
	handle:close()
	-- komut çıktısı sonu yeni satır karakterin silinmesi - en sondaki \n
	if result:sub(-1) == "\n" then
		result=result:sub(1,-2)
	end
	return result
end

print_star= function() cwrite("  *   ","lgreen") end
print_ok  = function() cwrite("[OK]\n","lgreen") end
print_fail=function() cwrite("[FAIL]\n","lred") end

-- take parameters
operation_p=arg[1]
task_p=arg[2]

premsg={start="Starting",stop="Stopping",status="Status"}

function drive(task,operation)
	t=require(task)
	-- check task/service has given operation 
	if t[operation] == nil then return 0 end
	print_star()
	local dprint=io.write 
	if action == print then dprint=print end
	dprint(("%s %-50s"):format(premsg[operation],t.desc))
	--log print todo!!!
	loconfig=config[task]
	kconfig=kernel_config(task)
	action=config.action
	result=nil
	-- task kendi custom start işlevine sahipse o koşulacak
	if type(t[operation]) == "function" then
		result=t[operation]()
	elseif type(t[operation]) == "table" then
		if t[operation]["cmd"] ~= nil then
			local cmd={}
			if type(t[operation]["cmd"]) == "table" then
				cmd=t[operation]["cmd"]
			elseif type(t[operation]["cmd"]) == "string" then
				table.insert(cmd,t[operation]["cmd"])
			else
				print(task,"servis hata: cmd tip yanlış")
			end 
			if next(cmd) ~= nil then
				-- run one by one
				-- onebyone result control olursa
				-- her komutun başarımı kontrol edilecek
				for _,c in ipairs(cmd) do
					-- en son komuta göre başarım kontrol edilecek
					-- başarım kontrolü için cmd index verilebilecek
					-- ona göre burası ayarlanacak
					result=action(c)
				end
			end
		end

		if t[operation]["type"] ~= nil then
			local op_type=t[operation]["type"]
			local cmd_table={
				program={
					start="nice -n 0 %s 2>&1 >/dev/null &",
					stop="killall	%s",
					status="ps -aux | grep %s | grep -v grep",
				},
				pid={
					stop="pkill -F %s",
					status=function(pid) 
						local _, pid_exist=l5.readlink(pid)
						if pid_exist == 2 then return false
						else return true end 
					end,
				}
			}
			if t[op_type] ~= nil then
				local cmd_obj=cmd_table[op_type][operation]
				if type(cmd_obj) == "string" then
					result=action(cmd_obj:format(t[op_type]))
				elseif type(cmd_obj) == "function" then
					result=cmd_obj(t[op_type])
				end
			else
				print(task,"servis hatası: bilinmeyen type!")
			end
		end

		-- start/stop operation içi boş olmamalı table olup ta
		-- kontrol edilmeli todo!!!
 	end
	if action == print then result=1 end
	if result then  
		print_ok()
		--log print todo!!!
	else
		print_fail()
		--log print todo!!!
	end
end

-- notlar
-- 0. servis tabiri yerine task kavramı üzerinden yapının semantiği kurulmalı.
-- 1.servisler parametre alacak mı ? almasına gerek yok servis kendi işlevinde configten almalı
-- 2.start işlevi birden fazla servisi çalıştıracak şekilde girdi almalı
-- eğer table ile çok servis verirse gelen sıraya göre start etmeli, core-task bunlar için olabilir.
-- 3. her config parametresi aynı zamanda kernel cmdline dan atanabilmeli
-- bunun için /proc/cmdline ayrıştırılmalı 
-- https://github.com/clwillingham/Tinycore-Scripted-Remaster/blob/master/src/extract/etc/init.d/tc-config#L49
-- yukarıdaki ayarlardan yararlanabilinir

tasks=config.tasks

if operation_p == nil then
	print("operation undefined")
end

-- single task drive
-- todo!!! çoklu için all parametre alınması uygun olabilir.
if operation_p ~= nil and task_p then
	drive(task_p,operation_p)
elseif operation_p == "start" then
	for _,task in ipairs(tasks) do
		drive(task,operation_p)
	end
elseif  operation_p == "stop" then
	-- reverse order
	for order,task in ipairs(tasks) do
		drive(tasks[#tasks-order+1],operation_p)
	end
end
